package cn.jtfadmin.base.shiro.support;

import cn.jtfadmin.base.lang.common.security.UserDetails;
import cn.jtfadmin.base.lang.config.ApplicationHolder;
import cn.jtfadmin.base.shiro.config.UserBuilder;
import cn.jtfadmin.base.shiro.events.UserBuildSuccessEvent;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class PrincipalUtils {


    public static PrincipalCollection createPrincipalCollection(UserDetails userDetails, String realmName) {
        return new SimplePrincipalCollection(userDetails, realmName);
    }


    public static UserDetails buildUserDetails( AuthenticationToken token){
        List<UserBuilder> userBuilders = getUserBuilders();
        UserDetails userDetails = null;
        for (UserBuilder userBuilder :userBuilders) {
            Optional<UserDetails> optional = userBuilder.build(token);
            if(optional.isPresent()){
                userDetails = optional.get();
                break;
            }
        }
        if(userDetails != null){
            pushEvent(userDetails, userDetails.getUserId(),userDetails.getType());
        }
        return userDetails;
    }

    private static void pushEvent(UserDetails userDetails, String userId, String userType){
        ApplicationHolder.getApplicationContext().publishEvent(new UserBuildSuccessEvent(userDetails, userId, userType));
    }


    private static List<UserBuilder> getUserBuilders(){
        String[] beanNamesForType = ApplicationHolder.getApplicationContext().getBeanNamesForType(UserBuilder.class);
        List<UserBuilder> collect = Arrays.stream(beanNamesForType).map(t -> ApplicationHolder.getApplicationContext().getBean(t, UserBuilder.class))
                .collect(Collectors.toList());
        return collect;
    }

    public static UserDetails buildUserDetailsOnly(String userId, String userType){
        List<UserBuilder> userBuilders = getUserBuilders();
        UserDetails userDetails = null;
        for (UserBuilder userBuilder : userBuilders) {
            Optional<UserDetails> optional = userBuilder.build(userId, userType);
            if(optional.isPresent()){
                userDetails = optional.get();
                break;
            }
        }
        return userDetails;
    }

    public static UserDetails buildUserDetails(String userId, String userType){
        List<UserBuilder> userBuilders = getUserBuilders();
        UserDetails userDetails = null;
        for (UserBuilder userBuilder : userBuilders) {
            Optional<UserDetails> optional = userBuilder.build(userId, userType);
            if(optional.isPresent()){
                userDetails = optional.get();
                break;
            }
        }
        if(userDetails != null){
            pushEvent(userDetails, userDetails.getUserId(),userDetails.getType());
        }
        return userDetails;
    }


//    private static void buildUserDetails(List<UserBuilder> userBuilders, UserDetails userDetails){
//        for(;;){
//            UserDetails news = null;
//            for (UserBuilder bean : userBuilders) {
//                Optional<UserDetails> optional = bean.build(userDetails);
//                if(optional.isPresent()){
//                    news = optional.get();
//                    break;
//                }
//            }
//            if(Objects.isNull(news)){
//                break;
//            }else {
//                userDetails.getUserDetailsSet().add(news);
//            }
//        }
//    }
}
